package amd64

import (
	"fmt"
	"strings"

	"gitee.com/u-language/u-language/ucom/ast"
	"gitee.com/u-language/u-language/ucom/internal/utils"
)

var Deferfunc func() = utils.Deferfunc

const (
	IncludeRun = `
	include 'win64a.inc' 
`
	_pe64  = "format PE64\n"
	_text  = "section '.text' code readable executable\n"
	_data  = "section '.data'  data readable writeable\n"
	_idata = `	section '.idata' import data readable writeable
	library kernel32,'KERNEL32.DLL'
	include 'api/kernel32.inc'`
	Exit = "invoke	ExitProcess,0\n"
)

type AstToAsm struct {
	Texts  *Text
	Datas  *Data
	Regrun *RegRun
	Sserun *SseRegRun
	Stack  *Stack
	VReg   *VReg
	Thread bool
}

func NewAstToAsm(Thread bool) *AstToAsm {
	return &AstToAsm{
		Texts:  NewText(Thread),
		Datas:  NewData(Thread),
		Regrun: NewRegRun(Thread),
		Sserun: NewSseRegRun(Thread),
		Stack:  nil,
		Thread: Thread,
		VReg:   NewVReg(),
	}
}

func (to *AstToAsm) Parser(ast *ast.Tree) {
	ret := ParserNode(to, ast.Nodes, ast.Sbt, to.Stack, to.VReg, false, to.Thread)
	if Debug == "true" { //调试时行为
		fmt.Println(ret)
	}
	AllocReg(ret, to.Regrun, to.Sserun, _NewvRegToReg(), _NewvregToRegTable(), to.Thread) //为虚拟寄存器分配实际寄存器
	to.Texts.AddSlice(ret)
	to.Datas.Silce()
	to.Texts.Silce()
}

func (to *AstToAsm) String() string {
	var buf strings.Builder
	buf.WriteString("ast to asm \n{")
	buf.WriteString(to.Texts.GoString())
	buf.WriteString(to.Datas.GoString())
	buf.WriteString("\n")
	buf.WriteString("}")
	return buf.String()
}

func (to *AstToAsm) Asm() string {
	var buf strings.Builder
	buf.Grow(10)
	buf.WriteString(_pe64)
	buf.WriteString(IncludeRun)
	buf.WriteString(to.Texts.Asm())
	buf.WriteString(to.Datas.Asm())
	buf.WriteString(_idata)
	return buf.String()
}
